package com.example.mq.mqserver.core;

import com.example.mq.common.Consumer;
import com.example.mq.common.ConsumerEnv;
import com.example.mq.common.MqException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 消息队列，正在存放消息的实体
 */
@Data
public class MSGQueue implements Serializable {

    //表示当前队列的唯一身份标识
    private String name;

    //是否持久化
    private boolean durable;

    //自动删除，队列没有人用是否删除
    private boolean autoDelete;

    //是否要独占，如果为true，表示当队列只能一个消费者使用，为false，表示多个消费者都可以使用
    //这个功能也暂时不实现(RabbitMQ中有的)
    private boolean exclusive;

    //由于如果要存进数据库，所以这里要将Map类型进行转化成json字符串，然后存储进去
    //Mybaits操作数据库，是调用java对象的getter方法，然后赋给对应字段
    //表示扩展的一些参数，先列在这里，后续如果要用，可以随时添加(RabbitMQ中有的)
    private Map<String,Object> arguments = new HashMap<>();

    //当前队列中管理哪些消费者
    private List<ConsumerEnv> consumerEnvList = new ArrayList<>();

    //当前取到了第几个消费者，方便进行轮策略(考虑到线程安全问题，可以直接使用atomic原子类)
    private AtomicInteger consumerSeq = new AtomicInteger(0);

    //使用下面类进行json字符串和java对象的转化
    private ObjectMapper objectMapper = new ObjectMapper();
    public String getArguments() {
        try {
            return objectMapper.writeValueAsString(arguments);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    public void setArguments(String jsonArguments) {
        try {
            objectMapper.readValue(jsonArguments, new TypeReference<Map<String,Object>>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    public void setArguments(Map<String,Object> arguments) {
        this.arguments = arguments;
    }

    public void addConsumerEnv(ConsumerEnv consumerEnv) {
        consumerEnvList.add(consumerEnv);
    }
    public void removeConsumerEnv(ConsumerEnv consumerEnv) {
        consumerEnvList.remove(consumerEnv);
    }
    public ConsumerEnv chooseConsumerEnvExclusive() {
        if(consumerEnvList.size() == 0) {
            //当前队列没人订阅
            return null;
        }
        int index = consumerSeq.get() % consumerEnvList.size();
        consumerSeq.incrementAndGet();
        return consumerEnvList.get(index);
    }
}
